package jmine.tec.database.pack.zip;

import static jmine.tec.database.pack.PackingMessages.IO_EXCEPTION;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import jmine.tec.database.pack.Pack;
import jmine.tec.database.pack.PackElement;
import jmine.tec.database.pack.PackException;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

/**
 * Utilitário que converte um pack em um arquivo compatível com um Pacote de Importação.
 * 
 * @author lundberg
 */
public class PackToZip {

    public static final String ARQUIVO_LISTA_IMPORTACAO = "importar_arquivos.txt";

    public static final String TOKEN_SEPARADOR = "|";

    /**
     * Escreve no output o pack como um Pacote de Importação de Arquivos
     * 
     * @param output output
     * @param pack pack
     * @throws PackException PackException
     */
    public void write(OutputStream output, Pack pack) throws PackException {
        try {
            ZipOutputStream zipOutput = new ZipOutputStream(output);
            StringBuilder builder = new StringBuilder();
            for (PackElement exec : pack.getElements()) {
                String fileName = StringUtils.join(exec.getPath(), "/").replaceAll("[^\\p{ASCII}]", "");
                builder.append(String.format("%s%s%s\r\n", fileName, TOKEN_SEPARADOR, exec.getFileCode()));

                InputStream in = exec.getInput();

                this.addToZip(zipOutput, fileName, in);
            }
            this.addToZip(zipOutput, ARQUIVO_LISTA_IMPORTACAO, new ByteArrayInputStream(builder.toString().getBytes("UTF-8")));

            zipOutput.close();
        } catch (IOException e) {
            throw new PackException(IO_EXCEPTION, e);
        }
    }

    /**
     * Adiciona um arquivo ao zip.
     * 
     * @param zipOutput zipOutput
     * @param fileName fileName
     * @param input input
     * @throws IOException IOException
     */
    private void addToZip(ZipOutputStream zipOutput, String fileName, InputStream input) throws IOException {
        try {
            zipOutput.putNextEntry(new ZipEntry(fileName));
            IOUtils.copy(input, zipOutput);
            zipOutput.closeEntry();
        } finally {
            input.close();
        }
    }
}
